//
//  PolicyManager.m
//  gdemm
//
//  Created by 乔明超 on 16/3/29.
//  Copyright © 2016年 Goldencis. All rights reserved.
//

#import "PolicyManager.h"
#import "ApiSupport.h"
#import "LocationPolicyManager.h"
#import "StringUtil.h"
#import "FileUtil.h"
#import "ToastManager.h"
#import "WaterMarkPolicyManager.h"
#import "SVProgressHUD.h"
#import "VPNManager.h"
#import "GeoFencing.h"
#import "WbAuditManager.h"
#import "DesktopPolicy.h"
#import "CallLimit.h"
@interface PolicyManager()
@property (nonatomic,strong) NSCondition *conditon;
@property (nonatomic,strong) NSMutableDictionary *mPolicyHandlers;
@property (nonatomic,strong) NSMutableDictionary *mPolicies;
@property (nonatomic,strong) NSMutableArray *mNPPolicies;
@property (nonatomic,assign) BOOL mUpdatePolicy;
@property (nonatomic,assign) BOOL mSilent;

@property (nonatomic,strong) LocationPolicyManager *mLocalManager;
@property (nonatomic,strong) NSString *mPolicyFile;

@end
@implementation PolicyManager
static PolicyManager *_instance;

//初始化对象创建所必须的一些属性和方法
- (instancetype)init
{
    self = [super init];
    if (self) {
        _mUpdatePolicy = NO;
        _mSilent = YES;
        _mIsLocalPolicy = NO;
        _mLocalManager = [LocationPolicyManager getInstance];
        [[HeartBeat shareInstance]addOnlineStateListener:self];
        [self addPolicyHandlers];
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self policyThread];
            
        });
    }
    return self;
}
#pragma mark 懒加载
//创建线程等待和线程唤醒对象
- (NSCondition *)conditon{
    if (_conditon == nil) {
        _conditon = [[NSCondition alloc]init];
    }
    
    return _conditon;
}
//存放支持的策略类型,如forbidBluetooth,forbidCamera
- (NSMutableDictionary *)mPolicyHandlers{

    if (_mPolicyHandlers == nil) {
        _mPolicyHandlers = [NSMutableDictionary dictionary];
    }
    return _mPolicyHandlers;
}

//存放有参策略,格式为{policyType : policyContent}
- (NSMutableDictionary *)mPolicies{
    if (_mPolicies == nil) {
        _mPolicies = [NSMutableDictionary dictionary];
        
    }
    return _mPolicies;
}
//存放无参策略,格式为[policyType]
- (NSMutableArray *)mNPPolicies{
    if (_mNPPolicies == nil) {
        _mNPPolicies = [NSMutableArray array];
    }
    return _mNPPolicies;
}

//获取PolicyManager单例,在app登录之后加载该单例
+ (instancetype)getInstance{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc]init];
    });
    return _instance;
    
}

//添加所支持的策略处理器
- (void)addPolicyHandlers{
    [self addPolicyHandlerWithPolicyHandler:[VPNManager getInstance]];
    [self addPolicyHandlerWithPolicyHandler:[WaterMarkPolicyManager getInstence]];
    [self addPolicyHandlerWithPolicyHandler:[GeoFencing getInstance]];
    [self addPolicyHandlerWithPolicyHandler:[WbAuditManager getInstance]];
    [self addPolicyHandlerWithPolicyHandler:[DesktopPolicy getInstence]];
    [self addPolicyHandlerWithPolicyHandler:[CallLimit getInstance]];
}

//设备上获取策略文件的路径
- (NSString *)getPolicyFile{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *dir = [paths[0] stringByAppendingPathComponent:@"config"];
    if (![FileUtil mkdirWithPath:dir]) {
        HRLog(@"make policy dir failed%@",dir);
    }
    return [dir stringByAppendingPathComponent:@"policies.json"];
}

//下载策略
- (BOOL)downloadPolicy{
    NSString *policyUrl = [ApiSupport getPolicyUrl];
    if (policyUrl == nil) {
        
    }else{
        NSString *tmpPolicyFile = [self getPolicyFile];
        if (tmpPolicyFile != nil) {
            tmpPolicyFile = [tmpPolicyFile stringByAppendingString:@".tmp"];
            if (![HttpUtil downloadTofileWithUrl:policyUrl withFileName:tmpPolicyFile]) {
                HRLog(@"download policy file failed");
                
            }else{
                NSFileManager *fileMgr  = [NSFileManager defaultManager];
                if ([fileMgr fileExistsAtPath:tmpPolicyFile]) {
                    NSString *origin = [self getPolicyFile];
                    [fileMgr removeItemAtPath:origin error:nil];
                    [fileMgr moveItemAtPath:tmpPolicyFile toPath:origin error:nil];
                    return YES;
                }
            }
        }
    }
    
    return NO;
}

- (BOOL)policyTimeHitTest:(NSString *)policyTime{
//    BOOL bHit = NO;
    
    return YES;
}




//把支持的策略处理器以及的策略类型保存到字典中
- (BOOL) addPolicyHandlerWithPolicyHandler:(id<PolicyHandler>)handler{

    NSString *supportPolicies = [handler supportPolicy];
    if (supportPolicies == nil) {
        return NO;
    }
    BOOL success = NO;
    NSArray *policies = [supportPolicies componentsSeparatedByString:@";"];
    for (NSString *policy in policies) {
        //一个策略只能被接管一次,后续的对同一策略的接管会失败
        if ([self.mPolicyHandlers objectForKey:policy] == nil) {
            [self.mPolicyHandlers setValue:handler forKey:policy];
            success = YES;
        }
        
    }
    return success;
}

//调用策略处理器实现的开始策略的协议方法
- (void)startPolicyWithPolicyType:(NSString *)policyType withPolicyContent:(NSDictionary *)policyContent{

    //HRLog(@"content = %@",policyContent);
    id<PolicyHandler> handler = [self.mPolicyHandlers objectForKey:policyType];
    if (handler != nil) {
        HRLog(@"startPolicy:%@ - %@",policyType,((policyContent != nil) ? policyContent : @""));
        [handler startPolicyWithPolicyType:policyType policyContent:policyContent];
    }else{
        HRLog(@"startPolicy PolicyHandler not found:%@",policyType);
    }
}

//调用策略处理器实现的停止策略的协议方法
- (void)stopPolicyWithPolicyType:(NSString *)policyType{
    id<PolicyHandler> handler = [self.mPolicyHandlers objectForKey:policyType];
    if (handler != nil) {
        HRLog(@"stopPolicy:%@",policyType);
        [handler stopPolicyWithPolicyType:policyType];
    }else{
        HRLog(@"stopPolicy PolicyHandler not found:%@",policyType);
    }
    
}

//
- (void)comparePoliciesWithPoliciew:(NSMutableDictionary *)policies{

    [policies enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        NSDictionary *content = self.mPolicies[key];
          HRLog(@"content  == %@ obj = %@",policies,obj);
        //策略新增或变更,都应重新派发
        if (content == nil || ![content isEqual:obj]) {
            [self startPolicyWithPolicyType:key withPolicyContent:obj];
        }
    }];
    
    //策略减少
    [self.mPolicies enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        if (policies[key] == nil) {
            [self stopPolicyWithPolicyType:key];
        }
    }];
    //将本次策略记录记录进内存
    self.mPolicies = policies;
}

- (void)compareNPPoliciesWithNpPolicies:(NSMutableArray *)npPolicies{
    for (NSString *policyType in npPolicies) {
        if ([self.mNPPolicies indexOfObject:policyType] == NSNotFound) {
            [self startPolicyWithPolicyType:policyType withPolicyContent:nil];
        }
    }
    
    for (NSString *policyType in self.mNPPolicies) {
        if ([npPolicies indexOfObject:policyType] == NSNotFound) {
            [self stopPolicyWithPolicyType:policyType];
        }
    }
    
    //将本次无参策略记录额记录进内存
    self.mNPPolicies = npPolicies;
}

//从本地策略文件获取所需要开启的策略类型,分为有参策略类型和无参策略类型,
- (void)dispatchPolicy{

   
    NSMutableDictionary *curPolicies = [NSMutableDictionary dictionary];
    NSMutableArray *curNPPolicies = [NSMutableArray array];
    NSString *policyFile = [self.mLocalManager searchLocationPolicyFile];
    if ([StringUtil isEmpty:policyFile]) {
        HRLog(@"区域策略未开启");
        policyFile = [self getPolicyFile];
        self.mIsLocalPolicy = NO;
    }else{
    
//        HRLog(@"区域策略已开启");
//        if (![policyFile containsString:@".json"]) {
//            policyFile = [policyFile stringByAppendingString:@".json"];
//            
//        }
//        self.mIsLocalPolicy = YES;
        policyFile = [self getPolicyFile];
        self.mIsLocalPolicy = NO;
    }
    
    HRLog(@"区域策略文件路径: %@",policyFile);
    self.mPolicyFile = policyFile;
    if (policyFile != nil && [FileUtil isFileExistWithFilePath:policyFile]) {
        
        NSDictionary *policies = [NSDictionary dictionaryWithContentsOfFile:policyFile];
        HRLog(@"策略内容 = %@",policies);
        if (self.mIsLocalPolicy) {
            policies = [policies objectForKey:@"policy"];
            
        }
        
        [policies enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        
            if ([obj isKindOfClass:[NSDictionary class]]) {
                if ([obj allKeys].count == 0) {
                    [curNPPolicies addObject:key];
                }else{
                    
                    NSDictionary *content = [obj objectForKey:@"content"];
                    [curPolicies setObject:content forKey:key];
                }
            }else{
                [curNPPolicies addObject:key];
                
            }
            
                
            }];
        
            
        
        }
        HRLog(@"NPP = %@,P = %@",curNPPolicies,curPolicies);
        [self comparePoliciesWithPoliciew:curPolicies];
        [self compareNPPoliciesWithNpPolicies:curNPPolicies];
        
        
    
}

//策略线程负责下载和派发策略
- (void)policyThread{

    BOOL first = YES;
    for (; ; ) {
        [self dispatchPolicy];
        // 首次立即重新派发，上面之所以先派发一次是为了防止可能的策略删除未响应，如：
        // 上次在线期间有禁用摄像头，也确实禁用了，后来离线了，第二天启动时下载的新策略
        // 中没有禁用摄像头了，会导致已经禁用的摄像头没有机会再恢复
       
        if (first) {
            first = NO;
            if (self.mIsLocalPolicy ? [self.mLocalManager downloadAndParsePolicy] : [self downloadPolicy]) {
                continue;
                
            }
            
        }
        
        [self.conditon lock];
        NSDate *date = [NSDate dateWithTimeIntervalSinceNow:5];
        [self.conditon waitUntilDate:date];
        [self.conditon unlock];
        
        if (self.mUpdatePolicy) {
            self.mUpdatePolicy = NO;
            BOOL success = [self downloadPolicy] && [self.mLocalManager downloadAndParsePolicy];
            if (!self.mSilent) {
                
                dispatch_async(dispatch_get_main_queue(), ^{
                    UIWindow *window = [UIApplication sharedApplication].keyWindow;
                    [window makeToast:(success ? NSLocalizedString(@"str_policyUpdateSuccess","策略更新成功") :NSLocalizedString(@"str_policyUpdateFailed","策略更新失败"))];
                });
               
                self.mSilent = YES;
            }
        }
    }
}

//策略更新的时候调用
- (void)updatePolicyWithsilent:(BOOL)silent{
    self.mUpdatePolicy = YES;
    self.mSilent = silent;
    [self.conditon lock];
    // 通知等待线程去下载
    [self.conditon broadcast];
    [self.conditon unlock];
}


//上线之后更新策略
- (void)onLine:(BOOL)isOnLine{
    if (isOnLine) {
        HRLog(@"client online now,update policy");
        [self updatePolicyWithsilent:YES];
        
    }

}

/**
 *  清除区域策略和用户策略
 */
- (void)clearPolicies{
    NSString *policiesFile = [self getPolicyFile];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *localFile = [paths[0] stringByAppendingString:@"/local_config/"];
    
    if ([FileUtil isFileExistWithFilePath:localFile]) {
        NSArray *fileList = [FileUtil getFileListFromDirectory:localFile];
        for (int i = 0;  i < fileList.count; i++) {
            NSString *filePath = [localFile stringByAppendingString:fileList[i]];
            [FileUtil deleteFileWithfilePath:filePath];
        }
        
    }
    
    if ([FileUtil isFileExistWithFilePath:policiesFile]) {
        [FileUtil deleteFileWithfilePath:policiesFile];
        [self dispatchPolicy];
    }
    
    
}
@end

